#include <iostream>
#include <future>
#include <thread>

/* 
    std::packaged_task是一个类模板，顾名思义是用来打包的，将一个可调用对象封装起来，然后可以将其的返回值传给future。
    std::packaged_task<函数返回类型(参数类型)> 变量名(函数名)。
    下面展示一下std::packaged_task()的简单用法，也可以将函数换成lambda表达式。
*/

/*
    std::future是一个类模板，提供了一个访问异步操作的结果的机制。
    我们可以通过future_status去查询future的三种状态，分别是
    deferred(还未执行)，ready(已经完成)，timeout(执行超时)，
    所以我们可以通过这个去查询异步操作的状态。
    future提供了一些函数比如get(),wait(),wait_for()，一般用get()来获取future所得到的结果，
    如果异步操作还没有结束，那么会在此阻塞的等待异步操作的结束，并获取返回的结果。
    wait()只是在此等待异步操作的结束，并不能获得返回结果。wait_for()超时等待返回结果。
*/

/*不过std::packaged_task<>实例是不可拷贝的，仅可移动，*/

int fun(int x) {
	x++;
	x *= 10;
	std::cout << std::this_thread::get_id() << std::endl;
	std::this_thread::sleep_for(std::chrono::seconds(5));
	return x;
}


int main()
{
    // 将函数打包起来
	std::packaged_task<int(int)> pt(fun);

    // 并将结果返回给future        
	std::future<int> fu = pt.get_future();        

    // std::packaged_task将一个可调用对象封装起来
    // 它的内部的operator()调用了构造他的可调用对象
	std::thread t(std::ref(pt), 1);

	std::cout << fu.get() << std::endl;
	std::cout << std::this_thread::get_id() << std::endl;
	t.join();
	return 0;
}